package com.alibaba.yinan.domain.task;

import com.alibaba.yinan.domain.common.AggregateRoot;
import com.alibaba.yinan.domain.task.resource.ResourceRequirement;
import com.alibaba.yinan.domain.task.service.lifecycle.TaskStateMachineHandler;
import com.alibaba.yinan.domain.task.service.policy.DispatchPolicySelector;
import com.alibaba.yinan.domain.task.service.strategy.TaskTypeStrategy;
import com.alibaba.yinan.domain.task.service.validator.DispatchValidatorChain;
import com.alibaba.yinan.domain.task.enums.DeviceType;
import com.alibaba.yinan.domain.task.enums.TaskEvent;
import com.alibaba.yinan.domain.task.enums.TaskStatus;
import com.alibaba.yinan.domain.task.enums.TaskType;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName TaskDomain
 * @Author mengke
 * @create 2025/8/2 14:47
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class Task extends AggregateRoot {

    private static final long serialVersionUID = 1L;

    /**
     * 任务ID
     */
    private String id;

    /**
     * 所属流程实例ID
     */
    private String processInstanceId;

    /**
     * 所属流程节点ID
     */
    private String nodeId;

    /**
     * 任务类型
     */
    private TaskType type;

    /**
     * 任务状态
     */
    private TaskStatus status;

    /**
     * 前置任务
     */
    private List<String> dependencies;

    /**
     * 目标设备类型
     */
    private DeviceType targetDeviceType;

    /**
     * 任务占用的载具孔位资源（可能跨多个载具）
     */
    private Map<String, List<String>> allocatedResources = new HashMap<>();

    /**
     * 任务资源需求声明
     */
    private ResourceRequirement resourceRequirement;

    /**
     * 运行设备ID
     */
    private String assignedDeviceId;

    /**
     * 分发策略
     */
    private List<String> dispatchPolicyKeys;

    /**
     * 预计运行时长
     */
    private Duration expectedDuration;

    /**
     * 任务创建时间
     */
    private Instant createTime;

    /**
     * 任务开始时间
     */
    private Instant startTime;

    /**
     * 任务结束时间
     */
    private Instant endTime;

    /**
     * 任务结果
     */
    private TaskResult result;


    /**
     * 生命周期状态切换（状态机驱动）
     */
    public void changeState(TaskEvent event, TaskStateMachineHandler handler) {
        this.status = handler.fireEvent(this.status, event);
    }

    /**
     * 调用任务类型策略行为（如执行前定制）
     */
    public void customizeByType(TaskTypeStrategy strategy) {
        strategy.customizeBehavior(this);
    }

    /**
     * 调用调度校验器链
     */
    public void validateBeforeDispatch(DispatchValidatorChain chain) {
        chain.validate(this);
    }

    /**
     * 调用调度策略决定设备分配
     */
    public void assignDevice(List<String> policyKeys, DispatchPolicySelector selector) {
        this.assignedDeviceId = selector.selectDevice(this, policyKeys);
    }

    /**
     * 任务是否已完成
     */
    public boolean isCompleted() {
        return TaskStatus.COMPLETED.equals(this.status) || TaskStatus.FAILED.equals(this.status);
    }

    /**
     * 绑定分配好的载具孔位
     */
    public void bindSlots(String cassetteCode, List<String> slotIds) {
        allocatedResources.put(cassetteCode, slotIds);
    }

    /**
     * 释放占用的资源
     */
    public void releaseSlots() {
        allocatedResources.clear();
    }

}
